
const { createClient, commandOptions } = require('redis');

const { md5 } = require('../helpers/function');

class Redis {
	constructor(options) {
		const { host, port, password, prefix } = options;
		this.prefix = prefix;

		this.client = createClient({
			url: `redis://:${password}@${host}:${port}`
		});

		this.client.on('error', (err) => {
			console.log(err);
		});

		this.client.on('ready', () => { })

		this.client.connect();
	}

	set(key, value, options, callback) {
		if (typeof value === 'object') value = JSON.stringify(value);

		return this.client.set.call(this.client, `${md5(this.prefix + key)}`, value, options, callback);
	}

	get(key, callback) {
		return this.client.get.call(this.client, `${md5(this.prefix + key)}`, callback).then((value) => {
			try {
				return JSON.parse(value);
			} catch (e) {
				return value;
			}
		});

		return this.client.get(`${md5(this.prefix + key)}`, callback).then((value) => {
			try {
				//JSON.parse(数值型字符串)不会报错，但是当数值大于2^53（9007199254740992），即数字型字符窜长度大于16的部分变成0。
				if (isNaN(parseInt(value))) return JSON.parse(value);
				return value;
			} catch (e) {
				return value;
			}
		})
	}

	lPush(key, value, callback) {
		return this.client.lPush.call(this.client, `${md5(this.prefix + key)}`, value, callback);
	}

	blPop(key, timeout, callback) {
		return this.client.blPop.call(this.client, commandOptions({
			isolated: true
		}), `${md5(this.prefix + key)}`, timeout || 0, callback);
	}

	//阻塞模式：当队列为空时，则在timeout时间内阻塞等待（timeout为0则一直阻塞等待），直到获取消息后退出
	/*
	 * redis-cli
	 * 127.0.0.1:6379> auth wiseidc
	 * OK
	 * 127.0.0.1:6379> brPop <key> 0

	 */
	brPop(key, timeout, callback) {
		return this.client.brPop.call(this.client, commandOptions({
			isolated: true
		}), `${md5(this.prefix + key)}`, timeout || 0, callback);
	}

	//非阻塞模式：当队列为空时，直接返回nil并退出等待
	/*
	 * 127.0.0.1:6379> rPop <key>
	 * (nil)
	 */
	rPop(key, callback) {
		return this.client.rPop.call(this.client, commandOptions({
			isolated: true
		}), `${md5(this.prefix + key)}`, callback);
	}
}

exports = module.exports = Redis;

module.exports.varal = () => {
	return ctn => {
		return new Redis(ctn.config.redis);
	};
};
